/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       windows_game.h

	$Header: /game/callstack_recoder.h $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#ifdef ENABLE_CALLSTACK_CODE

#include "callstack_recorder.h"

#define WIN32_LEAN_AND_MEAN
#define NOMINMAX

#include <map>
#include <string>
#include <windows.h>
#include <winnt.h>

#include "format_string.h"

#include "se_translator.h"
#include "exception_trap.h"
#include "unhandled_report.h"
#include "sym_engine.h"
#include "debug_stream.h"
#include "exception2.h"

std::ostream& get_ostream();
std::ostream& g_os = get_ostream();	

std::ostream& get_ostream()
{
	static dostream dos;
	//if (IsDebuggerPresent())
		return dos;
	//else 
	//	return std::cout;
}

int walk_callstack (EXCEPTION_POINTERS * except_info, std::ostream& os)
{
	// now it can print stack	
	sym_engine sym(0);
	
	sym_engine::stack_trace(g_os, sym, except_info->ContextRecord);

	g_os.flush();

	return 1;
}

const char* do_record_callstack(int calls_record)
{
	static std::ostringstream	    outstream;
	static std::string				output;

	__try
	{
		char * p = NULL;
		p[0] = 0;
	}
	__except( walk_callstack( GetExceptionInformation(), outstream ))
	{

	}

	return output.c_str();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
//use template specialziation to instrument the classes which you want to record call stack information for.
//must include the null parameter in the function definition, otherwise msvc++ will not correctly resolve the specialization.
////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct t_counted_ptr_id
{
	unsigned int	m_crc;			//crc of source origin, for faster lookup of counted ptr id.
	std::string		m_origin;		//source code origin
	unsigned int	m_instance;		//instance of the ptr from m_origin
};

std::map<unsigned int , t_counted_ptr_id > g_counted_ptr_map;

void record_callstack<t_adventure_map>(t_adventure_map * null)
{
	static unknown_caller_id = 0;

	std::string origin = do_record_callstack(1);
	
	/*
	if (origin.empty())
		origin = format_string("unknown_source_%i",unknown_caller_id++);

	unsigned int crc = calcuate_crc(origin.c_str(), origin.size());

	t_counted_ptr_id	counted_ptr_id;

	counted_ptr_id.m_crc		= crc;
	counted_ptr_id.m_origin		= origin;
	counted_ptr_id.m_instance	= 1;

	if (g_counted_ptr_map.find(crc) == g_counted_ptr_map.end())
	{
		g_counted_ptr_map[crc] = counted_ptr_id; 
	}
	else
	{
		g_counted_ptr_map[crc].m_instance++;
	}
	*/
}

#endif //ENABLE_CALLSTACK_CODE



